package com.dawn.module.hospital.service.medicalcopy;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.dawn.framework.common.exception.ServerException;
import com.dawn.framework.common.pojo.CommonResult;
import com.dawn.framework.common.util.string.StrUtils;
import com.dawn.module.hospital.controller.admin.medicalcopy.vo.MedicalCopyEndReqVO;
import com.dawn.module.hospital.controller.admin.medicalcopy.vo.MedicalCopyExamineReqVO;
import com.dawn.module.hospital.controller.admin.medicalcopy.vo.MedicalCopyPageReqVO;
import com.dawn.module.hospital.controller.admin.medicalcopy.vo.MedicalCopySaveReqVO;
import com.dawn.module.hospital.enums.BHConstants;
import com.dawn.module.hospital.enums.ErrorCodeConstants;
import com.dawn.module.hospital.enums.MedicalStatusEnum;
import com.dawn.module.hospital.model.pay.PayOrderCreateResModel;
import com.dawn.module.hospital.service.CDBPayUtils;
import com.dawn.module.hospital.service.TemplateMsgService;
import com.dawn.module.hospital.util.RandomUtils;
import com.dawn.module.hospital.util.SecEncryptUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;

import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;

import com.dawn.module.hospital.controller.app.medicalcopy.vo.*;
import com.dawn.module.hospital.dal.dataobject.medicalcopy.MedicalCopyDO;
import com.dawn.framework.common.pojo.PageResult;
import com.dawn.framework.common.pojo.PageParam;
import com.dawn.framework.common.util.object.BeanUtils;

import com.dawn.module.hospital.dal.mysql.medicalcopy.MedicalCopyMapper;

import static com.dawn.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.dawn.module.hospital.enums.ErrorCodeConstants.*;

/**
 * 病案复印 Service 实现类
 *
 * @author root
 */
@Service
@Validated
@Slf4j
public class MedicalCopyServiceImpl implements MedicalCopyService {

    @Resource
    private MedicalCopyMapper medicalCopyMapper;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private TemplateMsgService templateMsgService;
    @Override
    public Long createMedicalCopy(MedicalCopySaveReqVO createReqVO) {
        // 插入
        MedicalCopyDO medicalCopy = BeanUtils.toBean(createReqVO, MedicalCopyDO.class);
        String applyNo = "BA" + RandomUtils.buildRandomStr(4);
        medicalCopy.setApplyNo(applyNo);
        medicalCopy.setOrderNumber(applyNo);

        if("本人".equals(medicalCopy.getRelation())){
            medicalCopy.setApplicantName(medicalCopy.getPatientName());
            medicalCopy.setApplicantCardNo(medicalCopy.getPatientCardNo());
        }

        if(medicalCopy.getId() == null || medicalCopy.getId() == 0){
            medicalCopyMapper.insert(medicalCopy);
        }else {
            medicalCopyMapper.updateById(medicalCopy);
        }
        templateMsgService.sendMedicalApply(medicalCopy);
        // 返回
        return medicalCopy.getId();
    }

    @Override
    public void updateMedicalCopy(MedicalCopySaveReqVO updateReqVO) {
        // 校验存在
        validateMedicalCopyExists(updateReqVO.getId());
        // 更新
        MedicalCopyDO updateObj = BeanUtils.toBean(updateReqVO, MedicalCopyDO.class);
        medicalCopyMapper.updateById(updateObj);
    }

    @Override
    public void examineMedicalCopy(MedicalCopyExamineReqVO examineReqVO) {
        // 校验存在
        validateMedicalCopyExists(examineReqVO.getId());
        // 更新
        MedicalCopyDO updateObj = BeanUtils.toBean(examineReqVO, MedicalCopyDO.class);
        medicalCopyMapper.updateById(updateObj);

        MedicalCopyDO medicalCopyDO = getMedicalCopy(examineReqVO.getId());
        if(examineReqVO.getStatus() == MedicalStatusEnum.STATUS_EXAMINE_OK.getCode()){
            templateMsgService.sendMedicalExamineSuccess(medicalCopyDO);
        } else if (examineReqVO.getStatus() == MedicalStatusEnum.STATUS_EXAMINE_NO.getCode()) {
            templateMsgService.sendMedicalExamineFails(medicalCopyDO);
        }
    }

    @Override
    public void sendMedicalCopy(MedicalCopyEndReqVO endReqVO) {
        // 校验存在
        validateMedicalCopyExists(endReqVO.getId());
        // 更新
        MedicalCopyDO updateObj = BeanUtils.toBean(endReqVO, MedicalCopyDO.class);

        if("邮寄".equals(endReqVO.getCollectType())){
            updateObj.setStatus(MedicalStatusEnum.STATUS_SEND.getCode());
        } else {
            updateObj.setStatus(MedicalStatusEnum.STATUS_TAKE.getCode());
        }
        medicalCopyMapper.updateById(updateObj);

        MedicalCopyDO medicalCopyDO = getMedicalCopy(endReqVO.getId());
        if("邮寄".equals(endReqVO.getCollectType())){
            templateMsgService.sendMedicalDelivery(medicalCopyDO);
        } else {
            templateMsgService.sendMedicalTake(medicalCopyDO);
        }
    }

    @Override
    public void endMedicalCopy(MedicalCopyEndReqVO endReqVO) {
        // 校验存在
        validateMedicalCopyExists(endReqVO.getId());
        // 更新
        MedicalCopyDO updateObj = BeanUtils.toBean(endReqVO, MedicalCopyDO.class);

        updateObj.setStatus(MedicalStatusEnum.STATUS_END.getCode());
        medicalCopyMapper.updateById(updateObj);
    }

    @Override
    public void deleteMedicalCopy(Long id) {
        // 校验存在
        validateMedicalCopyExists(id);
        // 删除
        medicalCopyMapper.deleteById(id);
    }

    @Override
    public CommonResult payNotify(Map params){
        log.info("---------病案复印缴费成功通知-------params:"+ JSONUtil.toJsonStr(params));

        String orderNumber = String.valueOf(params.get("orderNumber"));
        String thirdOrderNo = String.valueOf(params.get("thirdOrderNo"));

        MedicalCopyDO medicalCopyDO = null;
        List<MedicalCopyDO> selectList = medicalCopyMapper.selectList(MedicalCopyDO::getOrderNumber,orderNumber);
        if(selectList.size()>0){
            medicalCopyDO = selectList.get(0);
        }

        if (medicalCopyDO == null) {
            throw exception(MEDICAL_COPY_NOT_EXISTS);
        }

        if (medicalCopyDO.getStatus() == 2) {
            return CommonResult.success("success");
        }

        medicalCopyDO.setThirdOrderNo(thirdOrderNo);
        medicalCopyDO.setPayTime(LocalDateTime.now());
        medicalCopyDO.setPayType(BHConstants.WEIXIN_SERVICE_ACCOUNTS.getMsg());
        medicalCopyDO.setPayStatus(2);
        medicalCopyMapper.updateById(medicalCopyDO);

        templateMsgService.sendMedicalPaySuccess(medicalCopyDO);
        templateMsgService.sendMedicalPayToAdmin(medicalCopyDO);

        return CommonResult.success("success");
    }

    @Override
    public CommonResult buildPaySignData(String applyNo) {
        MedicalCopyDO medicalCopyDO = getMedicalCopyByApplyNo(applyNo);
        if (medicalCopyDO == null) {
            throw exception(MEDICAL_COPY_NOT_EXISTS);
        }
        String orderNumber = "BAP" + RandomUtils.buildRandomStr(4);
        medicalCopyDO.setOrderNumber(orderNumber);
        medicalCopyMapper.updateById(medicalCopyDO);

        JSONObject object = JSONObject.parseObject(JSONObject.toJSONString(medicalCopyDO));
        object.put("orderNumber",medicalCopyDO.getApplyNo());
        object.put("totalCost",medicalCopyDO.getTotalPrice());

        Map<String,Object> map = new HashMap<>();
        map.putAll(object);
        JSONObject signDataJson = new JSONObject();
        signDataJson.put("patientId",medicalCopyDO.getPatientId());
        signDataJson.put("patientName",medicalCopyDO.getPatientName());
        signDataJson.put("clinicNo",medicalCopyDO.getHospitalNo());
        signDataJson.put("cardNo",medicalCopyDO.getPatientCardNo());
        signDataJson.put("pid",medicalCopyDO.getUserId());
        signDataJson.put("userId",medicalCopyDO.getUserId());
        signDataJson.put("openid",medicalCopyDO.getOpenid());
        signDataJson.put("registerNo",medicalCopyDO.getApplyNo());
        signDataJson.put("orderName","病案复印");
        signDataJson.put("totalCost",medicalCopyDO.getTotalPrice());
        signDataJson.put("orderNumber",orderNumber);

        stringRedisTemplate.opsForValue().set("OrderDetails_"+medicalCopyDO.getApplyNo(),signDataJson.toJSONString(),30L, TimeUnit.MINUTES);

        String signData = null;
        try {
            signData = SecEncryptUtil.encryption(signDataJson.toJSONString());
        } catch (Exception e) {
            throw new ServerException(ErrorCodeConstants.BH_ERROR.getCode(),e.getMessage());
        }
        map.put("signDataStr", signData);
        return CommonResult.success(map);

    }

    @Override
    public CommonResult queryByApplyNo(String applyNo) {
        MedicalCopyDO medicalCopyDO = getMedicalCopyByApplyNo(applyNo);
        if (medicalCopyDO == null) {
            throw exception(MEDICAL_COPY_NOT_EXISTS);
        }
        String orderNumber = "BAP" + RandomUtils.buildRandomStr(4);
        medicalCopyDO.setOrderNumber(orderNumber);
        medicalCopyMapper.updateById(medicalCopyDO);

        JSONObject object = JSONObject.parseObject(JSONObject.toJSONString(medicalCopyDO));
        object.put("orderNumber",medicalCopyDO.getApplyNo());
        object.put("totalCost",medicalCopyDO.getTotalPrice());
        if(medicalCopyDO.getPayStatus() == 2){
            object.put("payStatus","success");
        }
        return CommonResult.success(object);
    }

    @Override
    public MedicalCopyDO getMedicalCopyByApplyNo(String applyNo) {
        MedicalCopyDO medicalCopyDO = null;
        List<MedicalCopyDO> selectList = medicalCopyMapper.selectList(MedicalCopyDO::getApplyNo,applyNo);
        if(selectList.size()>0){
            medicalCopyDO = selectList.get(0);
        }
        return medicalCopyDO;
    }

    private void validateMedicalCopyExists(Long id) {
        if (medicalCopyMapper.selectById(id) == null) {
            throw exception(MEDICAL_COPY_NOT_EXISTS);
        }
    }

    @Override
    public MedicalCopyDO getMedicalCopy(Long id) {
        return medicalCopyMapper.selectById(id);
    }

    @Override
    public PageResult<MedicalCopyDO> getMedicalCopyPage(MedicalCopyPageReqVO pageReqVO) {
        return medicalCopyMapper.selectPage(pageReqVO);
    }

}